/*
* @file    :task_comm.c
* @module  :COMM TASK
* @author  :LingFengLu
* @date    :2023-06-08
*/

#include "task_comm.h"
#include "task.h"
#include "mid.h"
#include "drv.h"
#include "lib_string.h"
#include "lib_queue.h"
#include "lib_checksum.h"
#include "message.h"
#include "devos.h"
#include "devcomm.h"
#include "task_glucose.h"
//Constant definition    宏定义
#define TASK_COMM_ENCRYPTION               		1
#define TASK_COMM_ENCRYPTION_UPDATE         	1
#define TASK_COMM_SET_AUTHORITY					1

#define TASK_COMM_ADDRESS_LENGTH            	6
#define TASK_COMM_USER_ID_LENGTH            	32
#define TRANS_RATE_DEFAULT0                 	2
#define TRANS_RATE_DEFAULT1                 	1

#define ROLE_PRIMARY                        	1
#define ROLE_SECONDARY                      	0

#define TASK_COMM_PACKET_LENGTH_MAX			   	128
#define TASK_COMM_PACKET_LENGTH_MASTER		   	19
#define TASK_COMM_PACKET_LENGTH_SLAVE		   	32
#define TASK_COMM_SEND_RETRY				   	3
#define TASK_COMM_SEND_TIMEOUT				   	500
#define RECEIVE_BUFFER_SIZE                    	(BLE_MTU - BLE_GATT_ATT_OP_LEN - BLE_GATT_ATT_HANDLE_LEN)*2
#define LENGTH_BUFFER_SIZE			           	6
#define DATA_WRITE_BUFFER_SIZE                 	128
#define DATA_READ_BUFFER_SIZE                  	42
#define TASK_COMM_BUFFER_SIZE_MESSAGE          	160
#define TASK_COMM_BUFFER_SIZE_DEVICE_EVENT     	16
#define TASK_COMM_BUFFER_SIZE_COMMAND          	140

#define WRITE_DELAY_RATIO	1
#define PROCTIVELY_DISCONNECT                    8000
//Type definition    类型定义
typedef enum
{
	COMM_OPERATION_WRITE = 0,
	COMM_OPERATION_READ,
	COMM_COUNT_OPERATION
} comm_operation;

typedef struct
{
	uint8* u8_BufferData;
	uint8 u8_BufferLength[LENGTH_BUFFER_SIZE];
	lib_queue_object t_QueueData;
	lib_queue_object t_QueueLength;
} comm_control;

typedef struct
{
	uint8 u8_Address;
	uint8 u8_SourcePort;
	uint8 u8_TargetPort;
	uint8 u8_Mode;
	uint8 u8_Length;
} task_comm_message;

typedef enum
{
	TASK_COMM_DEVICE_RF= 0,
	TASK_COMM_COUNT_DEVICE
} task_comm_device;

typedef enum
{
	TASK_COMM_FLAG_SWITCH = 0,
	TASK_COMM_FLAG_BROADCAST_PENDING,
	TASK_COMM_FLAG_INFO_UPDATING,
	TASK_COMM_FLAG_BONDED,
	TASK_COMM_FLAG_PRIMARY,
	TASK_COMM_COUNT_FLAG
} task_comm_flag;

typedef enum
{
	TASK_COMM_EVENT_WRITE_DONE = 0,
	TASK_COMM_EVENT_READ_DONE,
	// TASK_COMM_EVENT_STATE_CHANGE,
	// TASK_COMM_EVENT_DELAY_WRITE_DONE_BROADCAST,
	// TASK_COMM_EVENT_DELAY_WRITE_DONE_CONNECTION,
	// TASK_COMM_EVENT_DELAY_SCAN,
	// TASK_COMM_EVENT_DELAY_CONNECTION,
	// TASK_COMM_EVENT_MANAGEMENT,
	TASK_COMM_COUNT_EVENT
} task_comm_event;

//Global variable definition    全局变量定义


//Private variable definition    私有变量定义
static const uint8 m_u8_Reboot[16] ={ 'f', 'o', 'r', 'c', 'e', ' ', 'r', 'e', 'b', 'o', 'o', 't', ' ', 'a', 'l', 'l' };
static const uint8 m_u8_RebootAsc[16] ={ 'f', 'o', 'r', 'c', 'e', ' ', 'r', 'e', 'b', 'o', 'o', 't', ' ', 'g', 'c' };
static const uint8 m_u8_ClearPairingInfo[16] ={ 'f', 'o', 'r', 'c', 'e', ' ', 'u', 'n', 'p', 'a', 'i', 'r', ' ', 'a', 'l', 'l' };
static const uint8 m_u8_GetLogNum[14] ={ 'g', 'e', 't', ' ', 'l', 'o', 'g', ' ', 'n', 'u', 'm', 'b', 'e', 'r' };
static const uint8 m_u8_Log[3] ={ 'l', 'o', 'g' };
static const uint8 m_u8_GetR[4] = { 'g', 'e', 't','r' };
static const uint8 m_u8_CalR[4] =  { 'c', 'a', 'l','r'  };
static const uint8 m_u8_GetPairInfo1[15] = { 'g', 'e', 't',' ','p','a','i','r',' ','i','n','f','o',' ','0' };
static const uint8 m_u8_GetPairInfo2[15] = { 'g', 'e', 't',' ','p','a','i','r',' ','i','n','f','o',' ','1' };
static uint m_ui_Flag[MESSAGE_COUNT_ADDRESS] = {0};
static uint m_ui_MessageID = 0;
static uint8 m_u8_BufferCommand[TASK_COMM_BUFFER_SIZE_COMMAND] = {0};
static uint8 m_u8_ReceiveBuff[RECEIVE_BUFFER_SIZE]={0};
static uint8 m_u8_ReceiveBuffBak[RECEIVE_BUFFER_SIZE] = {0};
static uint8 m_u8_BufferMessage[MESSAGE_COUNT_ADDRESS][TASK_COMM_BUFFER_SIZE_MESSAGE] = {0};
static const  uint8 m_u8_BufferMessageLength[MESSAGE_COUNT_ADDRESS] = {TASK_COMM_BUFFER_SIZE_MESSAGE, TASK_COMM_BUFFER_SIZE_MESSAGE};
static uint8 m_u8_BufferDeviceEvent[TASK_COMM_BUFFER_SIZE_DEVICE_EVENT];
static lib_queue_object m_t_QueueMessage[MESSAGE_COUNT_ADDRESS] = {0};
static lib_queue_object m_t_QueueDeviceEvent = {0};
static uint m_ui_ReadLength = 0;
static const uint8 *m_u8p_ReadData = {0};
static uint8 m_u8_WriteBufferData[DATA_WRITE_BUFFER_SIZE] = {0};
static uint8 m_u8_ReadBufferData[DATA_READ_BUFFER_SIZE] = {0};
static const uint8 m_u8_BufferSize[COMM_COUNT_OPERATION] = {DATA_WRITE_BUFFER_SIZE,DATA_READ_BUFFER_SIZE};
static uint8 m_u8_TempIv[KEYLEN] = {0};
// static const uint8 m_u8_PairingIDLength[TASK_COMM_COUNT_IDENTIFIER] = {TASK_COMM_ADDRESS_LENGTH, TASK_COMM_USER_ID_LENGTH};
static const uint8 m_u8_DefaultTransRate[TASK_COMM_COUNT_IDENTIFIER] = {TRANS_RATE_DEFAULT0, TRANS_RATE_DEFAULT1};
static uint8 m_u8_UpdateKeyFlag =0;
static uint16 m_u16_WriteDelayRatio = WRITE_DELAY_RATIO;
static task_comm_broadcast m_t_Broadcast = {0};
static uint16 m_u16_ConnectWriteDelayRatio = 1;
static uint16 m_u16_ConnectInterval = 0;
static comm_control m_t_CommControl[COMM_COUNT_OPERATION] = 
{
	{
		m_u8_WriteBufferData,{0},{0},{0}
	},
	{
		m_u8_ReadBufferData,{0},{0},{0}
	}
};
static pairing_info m_t_PairingInfo[TASK_COMM_COUNT_IDENTIFIER] =
{
	{
		{0},
		{0},
		{0},
		TASK_COMM_ADDRESS_LENGTH,
		TRANS_RATE_DEFAULT0,
		ROLE_SECONDARY,
		{0}
	},
	{
		
		{0},
		{0},
		{0},
		TASK_COMM_USER_ID_LENGTH,
		TRANS_RATE_DEFAULT1,
		ROLE_SECONDARY,
		{0}
	}
};

//Private function declaration   私有函数申明
static uint TaskComm_InitializeBle(void);
static uint TaskComm_InitializeComm(void);
static uint TaskComm_InitializeOS
( 
devos_task_handle t_TaskHandle
);
static uint TaskComm_GetDevice
( 
devcomm_int t_Address,
devcomm_int *tp_Device 
);

static void TaskComm_Tick
( 
uint16 u16_TickTime 
);
static void TaskComm_HandleMessage(void);
static uint TaskComm_CheckState
(
uint8 *u8p_State
);
static uint TaskComm_HandleEvent
( 
devcomm_int t_Device,
devcomm_int t_Address,
devcomm_int t_SourcePort,
devcomm_int t_TargetPort,
devcomm_int t_Event
);
static uint TaskComm_WriteDevice
( 
devcomm_int t_Device,
const uint8 *u8p_Data,
devcomm_int t_Length 
);
static uint TaskComm_Write
( 
const uint8 *u8p_Data,
uint ui_Length 
);
static uint TaskComm_ReadDevice
( 
devcomm_int t_Device,
uint8 *u8p_Data,
devcomm_int *tp_Length 
);
static uint TaskComm_Read
(
uint8 *u8p_Data,
uint *uip_Length 
);

static void TaskComm_Memcpy
( 
uint8 *u8p_Target, 
const uint8 *u8p_Source, 
devcomm_int t_Length 
);

static uint8 TaskComm_GetCRC8
( 
const uint8 *u8p_Data, 
devcomm_int t_Length, 
uint8 u8_Base 
);
static uint16 TaskComm_GetCRC16
( 
const uint8 *u8p_Data, 
devcomm_int t_Length, 
uint16 u16_Base 
);
static void TaskComm_EncryptionUpdate(void);

static void TaskComm_Encrypt
( 
uint8 *u8p_Data, 
devcomm_int t_Length 
);
static void TaskComm_Decrypt
( 
uint8 *u8p_Data, 
devcomm_int t_Length 
);
static uint TaskComm_SavePairingInfo(void);
static uint TaskComm_LoadPairingInfo(void);
static uint TaskComm_SendCommand
( 
uint8 u8_Address,
uint8 u8_SourcePort,
uint8 u8_TargetPort,
const message_command *tp_Command,
uint8 u8_Mode 
);
static void TaskComm_BleOnConnect(void);
static void TaskComm_BleDisOnConnect(void) ;
static void TaskComm_BleTimerCheck(void) ;
static void TaskComm_BleOnWrite
(
uint16 u16_ConnetHandle, 
uint16 u16_AttIndex, 
uint8 *u8p_Data, 
uint16 u16_Len
);

static void TaskComm_CommunicationServicOnWrite
(
uint8 * u8p_Data, 
uint16 u16_Length
);
static void TaskComm_ManagementServicOnWrite
(
uint8 * u8p_Data, 
uint16 u16_Length
);
static void TaskComm_CommandReceived
(
uint8 * u8p_Data, 
uint16 u16_Length
);
void TaskComm_InitFrame
( 
uint ui_Operation
);
void TaskComm_ResetFrame
( 
uint ui_Operation
);
static uint TaskComm_AddFrame
( 
uint ui_Operation,
const uint8 *u8p_Data,
uint ui_Length 
);
static uint TaskComm_PopFrame//TaskComm_RemoveFrame
( 
uint ui_Operation,
uint8 *u8p_Data,
uint *uip_Length
);
static uint TaskComm_ProcessFrame
( 
uint ui_Operation,
const uint8 *u8p_Data,
uint ui_Length 
);
static uint TaskComm_Notify
(    
uint16 u16_AttHandle,  
uint8 *u8p_Data, 
uint ui_Len
);
static void TaskComm_InitDeviceEvent(void);
static void TaskComm_StartWriteTimer
(
uint16 u16_Interval
);
static void TaskComm_WrtieTimerCallback(void *a);
static void TaskComm_WriteDone( void );

static uint TaskComm_HandleDeviceRfEvent
( 
uint ui_Event,
const uint8 *u8p_Data,
uint ui_Length 
);
static void TaskComm_UpdateBroadcast(void);
static void TaskComm_ClearQueueEvent(void);
static void Task_TimerCheck(void *a) ;
static void TaskComm_BleTimerCheck(void) ;
//Public function definition   公共函数定义
void TaskComm_Init
(
devos_task_handle t_TaskHandle
)
{
	if (TaskComm_InitializeBle() != FUNCTION_OK)
		return ;
	if (TaskComm_InitializeOS(t_TaskHandle) != FUNCTION_OK)
		return ;
	if (TaskComm_InitializeComm() != FUNCTION_OK)
		return ;
	if(TaskComm_LoadPairingInfo() != FUNCTION_OK)
		return;
}


void TaskComm_Process
(
devos_task_handle t_TaskHandle
)
{
	static uint8 *u8p_MessageData;
	static devos_int t_MessageLength;
	DEVOS_TASK_BEGIN
		
		DevOS_MessageWait(DEVOS_MESSAGE_COUNT_MAX, u8p_MessageData, &t_MessageLength);
	printf("TaskComm_Process\n");
	TaskComm_HandleMessage();
	DEVOS_TASK_END
}
uint TaskComm_SetConfig
(
uint ui_Parameter,
const uint8 *u8p_Value,
uint ui_Length
)
{
	switch (ui_Parameter)
	{
	    case TASK_COMM_PARAM_BROADCAST_DATA:
		Lib_Memcpy((uint8 *)&m_t_Broadcast, u8p_Value, ui_Length);
		TaskComm_UpdateBroadcast();
		break;
		
	    default:
		break;
	}
	return FUNCTION_OK;
}
uint TaskComm_GetConfig
(
uint ui_Parameter,
uint8 *u8p_Value,
uint *uip_Length
)
{
	switch (ui_Parameter)
	{
	    case TASK_COMM_PARAM_BUSY:
		
		if (TaskComm_CheckState(u8p_Value) != FUNCTION_OK)
			return FUNCTION_FAIL;
		break;
		
	    default:
		break;
	}
	return FUNCTION_OK;
}


uint TaskComm_Pair
( 
uint ui_Parameter,
uint8 *u8p_Value,
uint *uip_Length 
)
{
	LOG_INFO("TaskComm_Pair");
	pairing_info *tp_PairingInfo;
	uint8 u8_Acknowledge = FUNCTION_FAIL;
	
	uint8 u8_IdLength = m_t_PairingInfo[ui_Parameter].u8_PairingIDLength;
	if ( ( ui_Parameter == TASK_COMM_IDENTIFIER_ADDRESS ||
	      ui_Parameter == TASK_COMM_IDENTIFIER_USER_ID  ) &&
	    ( *uip_Length  == u8_IdLength                  ||
	     *uip_Length  == u8_IdLength + 1*sizeof(uint8)||
		     *uip_Length  == u8_IdLength + 2*sizeof(uint8) ) )
	{
		tp_PairingInfo = &m_t_PairingInfo[ui_Parameter];
		
		if ( Lib_Memcmpv(tp_PairingInfo->u8_PairingID, 0, tp_PairingInfo->u8_PairingIDLength) == FUNCTION_OK )
		{
			Lib_Memcpy(tp_PairingInfo->u8_PairingID, u8p_Value, tp_PairingInfo->u8_PairingIDLength);
			u8_Acknowledge = FUNCTION_OK;
		}
		else if ( Lib_Memcmp(tp_PairingInfo->u8_PairingID, u8p_Value, tp_PairingInfo->u8_PairingIDLength) == FUNCTION_OK )
		{
			u8_Acknowledge = FUNCTION_OK;
		}
	}
	
	if (u8_Acknowledge == FUNCTION_OK)
	{
		if ( *uip_Length == u8_IdLength + 1*sizeof(uint8) )
			tp_PairingInfo->u8_TransRate = u8p_Value[*uip_Length-1];
		else if ( *uip_Length == u8_IdLength )
			tp_PairingInfo->u8_TransRate = m_u8_DefaultTransRate[ui_Parameter];
		
		uint32 u32_Rand =1;
		u32_Rand = Drv_Random();
		LOG_INFO("Random:%d",u32_Rand);
		uint16 u16_Rand = (uint16)u32_Rand;
		//////////////////////////////////////////////////////////////////
		if(m_u8_UpdateKeyFlag == 1)
		{
			
			for (uint i=0; i<TASK_COMM_BOND_ID_LENGTH; i+=2)
			{
				Lib_Memcpy(tp_PairingInfo->u8_BondID+i, (const uint8 *)&u16_Rand, 2);
			}
			for (uint i=0; i<KEYLEN; i+=4)
			{
				u32_Rand = u32_Rand*99991+123457;
				Lib_Memcpy(tp_PairingInfo->u8_Key+i, (const uint8 *)&u32_Rand, 4);
			}
			
			
			for (uint8 i=0; i<TASK_COMM_COUNT_IDENTIFIER; i++)
			{
				if (i == ui_Parameter)
					m_t_PairingInfo[i].u8_Role = ROLE_PRIMARY;
				else
					m_t_PairingInfo[i].u8_Role = ROLE_SECONDARY;
			}
			u8_Acknowledge = TaskComm_SavePairingInfo();
			u8_Acknowledge =FUNCTION_OK ; 
			if(u8_Acknowledge == FUNCTION_FAIL)
			{
				*uip_Length = 1;
				return u8_Acknowledge;
			}
			m_u8_UpdateKeyFlag = 0;
		}
		
	}
	
	if(u8_Acknowledge == FUNCTION_FAIL)
	{
		*uip_Length= 1;
		return FUNCTION_FAIL;
	}
	
	
	if (u8_Acknowledge == FUNCTION_OK && *uip_Length == u8_IdLength + 2*sizeof(uint8))
	{
		TaskGlucose_SetConfig(TASK_GLUCOSE_PARAM_HYPO_HYPER,  u8p_Value+u8_IdLength,2*sizeof(uint8));
	}
	u8p_Value += 1;
	Lib_Memcpy(u8p_Value, tp_PairingInfo->u8_BondID, TASK_COMM_BOND_ID_LENGTH);
	u8p_Value += TASK_COMM_BOND_ID_LENGTH;
	Lib_Memcpy(u8p_Value, tp_PairingInfo->u8_Key, KEYLEN);
	*uip_Length = u8_Acknowledge == FUNCTION_OK? (1 + TASK_COMM_BOND_ID_LENGTH + KEYLEN) : 1;  
	return u8_Acknowledge;
}

uint TaskComm_Unpair
( 
uint ui_Parameter,
uint8 *u8p_Value,
uint *uip_Length 
)
{
	LOG_INFO("TaskComm_Unpair");
	pairing_info *tp_PairingInfo;
	pairing_info t_PairingInfoTemp={0};
	uint8 u8_Acknowledge = FUNCTION_FAIL;
	
	if (ui_Parameter < TASK_COMM_COUNT_IDENTIFIER)
	{
		tp_PairingInfo = &m_t_PairingInfo[ui_Parameter];
		Lib_Memcpy((uint8 *)&t_PairingInfoTemp,(uint8 *)tp_PairingInfo,sizeof(pairing_info));
		Lib_Memset(tp_PairingInfo->u8_PairingID, 0, tp_PairingInfo->u8_PairingIDLength);
		Lib_Memset(tp_PairingInfo->u8_BondID, 0, TASK_COMM_BOND_ID_LENGTH);
		
		
		
		
		tp_PairingInfo->u8_Role = ROLE_SECONDARY;
		u8_Acknowledge = TaskComm_SavePairingInfo();
		u8_Acknowledge =FUNCTION_OK ; 
		if(u8_Acknowledge == FUNCTION_FAIL)
		{
			Lib_Memcpy((uint8 *)tp_PairingInfo,(uint8 *)&t_PairingInfoTemp,sizeof(pairing_info));
		}
		
	}
	*uip_Length = 1;
	return u8_Acknowledge;
}

uint TaskComm_Bond
( 
uint ui_Parameter,
uint8 *u8p_Value,
uint *uip_Length 
)
{
	pairing_info *tp_PairingInfo;
	uint8 u8_Acknowledge = FUNCTION_FAIL;
	LOG_INFO("TaskComm_Bond");
	if (ui_Parameter < TASK_COMM_COUNT_IDENTIFIER && (*uip_Length == TASK_COMM_BOND_ID_LENGTH || *uip_Length == TASK_COMM_BOND_ID_LENGTH+1))
	{
		tp_PairingInfo = &m_t_PairingInfo[ui_Parameter];
		if ( Lib_Memcmpv( tp_PairingInfo->u8_BondID, 0, TASK_COMM_BOND_ID_LENGTH ) != FUNCTION_OK &&
		    Lib_Memcmp( tp_PairingInfo->u8_BondID, u8p_Value,      TASK_COMM_BOND_ID_LENGTH ) == FUNCTION_OK   )
			u8_Acknowledge = FUNCTION_OK;
	}
	
#if TASK_COMM_ENCRYPTION
#if TASK_COMM_ENCRYPTION_UPDATE
	if (u8_Acknowledge == FUNCTION_OK)
		u8_Acknowledge = DevComm_SwitchEncryption( TASK_COMM_DEVICE_RF,
							  MESSAGE_ADDRESS_MASTER,
							  DEVCOMM_ENCRYPTION_UPDATE );
#else
	if (u8_Acknowledge == FUNCTION_OK)
		u8_Acknowledge = DevComm_SwitchEncryption( TASK_COMM_DEVICE_RF,
							  MESSAGE_ADDRESS_MASTER,
							  DEVCOMM_ENCRYPTION_ON );
#endif
#endif
	
	if (u8_Acknowledge == FUNCTION_OK)
	{
		uint8 u8_TransRate;
		if (*uip_Length > TASK_COMM_BOND_ID_LENGTH)
			u8_TransRate = *(u8p_Value+TASK_COMM_BOND_ID_LENGTH);
		else
			u8_TransRate = tp_PairingInfo->u8_TransRate;
		REG_SET_BIT(m_ui_Flag[MESSAGE_ADDRESS_MASTER], TASK_COMM_FLAG_BONDED);
		if (tp_PairingInfo->u8_Role == ROLE_PRIMARY)
		{
			REG_SET_BIT(m_ui_Flag[MESSAGE_ADDRESS_MASTER], TASK_COMM_FLAG_PRIMARY);
		}
		DevComm_Link( TASK_COMM_DEVICE_RF,
			     MESSAGE_ADDRESS_MASTER,
			     19 * u8_TransRate );
		*uip_Length = 1;
#if TASK_COMM_ENCRYPTION
		AES_SetKey(tp_PairingInfo->u8_Key, 0);
#if TASK_COMM_ENCRYPTION_UPDATE
		uint32 u32_Rand =1;
		u32_Rand = Drv_Random();
		for (uint8 i=0; i<KEYLEN; i+=4)
		{
			u32_Rand = u32_Rand*99991+123457;
			Lib_Memcpy(m_u8_TempIv+i, (const uint8 *)&u32_Rand, 4);
		}
		
		Lib_Memcpy(u8p_Value, m_u8_TempIv, KEYLEN);
		u8p_Value[KEYLEN] = LibChecksum_GetChecksum8Bit(u8p_Value, KEYLEN);
		*uip_Length = KEYLEN + 1;
		
		if(ui_Parameter == TASK_COMM_IDENTIFIER_ADDRESS)
		{
			m_u16_WriteDelayRatio = WRITE_DELAY_RATIO+1;
		}
		else if(ui_Parameter == TASK_COMM_IDENTIFIER_USER_ID)
		{
			m_u16_WriteDelayRatio = WRITE_DELAY_RATIO;
		}
		
#endif
#endif
	}
	else
	{
		*uip_Length = 0;
	}
	
	
	return u8_Acknowledge;
}

uint TaskComm_Send
( 
uint8 u8_Address,
uint8 u8_SourcePort,
uint8 u8_TargetPort,
message_command *tp_Command,
uint8 u8_Mode 
)
{
	LOG_INFO("TaskComm_Send-Adr:%d,sp:%d,tp:%d",u8_Address,u8_SourcePort,u8_TargetPort);
	uint ui_Value;
	devcomm_int t_Device;
	devcomm_int t_State;
	task_comm_message t_Message;
	
	if ( u8_Address >= MESSAGE_COUNT_ADDRESS )
		return FUNCTION_FAIL;
	
	if ( TaskComm_GetDevice((devcomm_int)u8_Address, &t_Device) != FUNCTION_OK )
		return FUNCTION_FAIL;
	
	if ( DevComm_Query(t_Device, (devcomm_int)u8_Address, DEVCOMM_INFO_STATE, &t_State) != FUNCTION_OK )
		return FUNCTION_FAIL;
	if (t_State == DEVCOMM_STATE_BUSY)
	{
		if ( LibQueue_GetConfig( &m_t_QueueMessage[u8_Address],
					LIB_QUEUE_PARAM_BUFFER_SPACE,
					(void *)&ui_Value ) != FUNCTION_OK )
			return FUNCTION_FAIL;
		
		t_Message.u8_Address = u8_Address;
		t_Message.u8_SourcePort = u8_SourcePort;
		t_Message.u8_TargetPort = u8_TargetPort;
		t_Message.u8_Mode = u8_Mode;
		
		if (tp_Command == (const message_command *)0)
		{
			if (ui_Value < sizeof(task_comm_message))
				return FUNCTION_FAIL;
			
			t_Message.u8_Length = 0;
			ui_Value = sizeof(t_Message);
			
			if ( LibQueue_PushTail( &m_t_QueueMessage[u8_Address],
					       (const uint8 *)&t_Message,
					       &ui_Value ) != FUNCTION_OK )
				return FUNCTION_FAIL;
		}
		else
		{
			if ( ui_Value < sizeof(task_comm_message)+MESSAGE_COUNT_COMMAND_OFFSET+tp_Command->u8_Length )
				return FUNCTION_FAIL;
			
			t_Message.u8_Length = MESSAGE_COUNT_COMMAND_OFFSET + tp_Command->u8_Length;
			ui_Value = sizeof(t_Message);
			if ( LibQueue_PushTail( &m_t_QueueMessage[u8_Address],
					       (const uint8 *)&t_Message,
					       &ui_Value ) != FUNCTION_OK )
				return FUNCTION_FAIL;
			
			ui_Value = MESSAGE_COUNT_COMMAND_OFFSET;
			if ( LibQueue_PushTail( &m_t_QueueMessage[u8_Address],
					       (const uint8 *)tp_Command,
					       &ui_Value ) != FUNCTION_OK )
				return FUNCTION_FAIL;
			
			ui_Value = (uint)tp_Command->u8_Length;
			if ( LibQueue_PushTail( &m_t_QueueMessage[u8_Address],
					       tp_Command->u8p_Data,
					       &ui_Value ) != FUNCTION_OK )
				return FUNCTION_FAIL;
		}
	}
	else
	{
		return TaskComm_SendCommand( u8_Address,
					    u8_SourcePort,
					    u8_TargetPort,
					    tp_Command,
					    u8_Mode );
	}
	
	return FUNCTION_OK;
}


uint TaskComm_Receive
( 
uint8 u8_Address,
uint8 *u8p_SourcePort,
uint8 *u8p_TargetPort,
message_command *tp_Command,
uint8 *u8p_Mode 
)
{
	devcomm_int t_Device;
	devcomm_int t_Length;
	devcomm_int t_SourcePort;
	devcomm_int t_TargetPort;
	devcomm_int t_Mode;
	
	if (TaskComm_GetDevice((devcomm_int)u8_Address, &t_Device) != FUNCTION_OK)
		return FUNCTION_FAIL;
	
	if (REG_GET_BIT(m_ui_Flag[u8_Address], TASK_COMM_FLAG_SWITCH) == 0)
		return FUNCTION_FAIL;
	
	if ( DevComm_Receive( t_Device, (devcomm_int)u8_Address,
			     &t_SourcePort,
			     &t_TargetPort,
			     m_u8_BufferCommand,
			     &t_Length,
			     &t_Mode ) != FUNCTION_OK )
		return FUNCTION_FAIL;
	
	if (t_Length < MESSAGE_COUNT_COMMAND_OFFSET)
		return FUNCTION_FAIL;
	
	*u8p_SourcePort = (uint8)t_SourcePort;
	*u8p_TargetPort = (uint8)t_TargetPort;
	*u8p_Mode = (uint8)t_Mode;
	tp_Command->u8_Operation = m_u8_BufferCommand[MESSAGE_COMMAND_OFFSET_OPERATION];
	tp_Command->u8_Parameter = m_u8_BufferCommand[MESSAGE_COMMAND_OFFSET_PARAMETER];
	tp_Command->u8_Length = (uint8)t_Length - MESSAGE_COUNT_COMMAND_OFFSET;
	tp_Command->u8p_Data = &m_u8_BufferCommand[MESSAGE_COUNT_COMMAND_OFFSET];
	
	return FUNCTION_OK;
}

void TaskComm_ClearQueueMessage(void)
{
	Lib_Memset(m_u8_BufferMessage[MESSAGE_ADDRESS_MASTER],0,TASK_COMM_BUFFER_SIZE_MESSAGE);
	Lib_Memset(m_u8_BufferMessage[MESSAGE_ADDRESS_SLAVE],0,TASK_COMM_BUFFER_SIZE_MESSAGE);
	LibQueue_Initialize( &m_t_QueueMessage[MESSAGE_ADDRESS_MASTER],
			    (uint8 *)&m_u8_BufferMessage[MESSAGE_ADDRESS_MASTER],
			    TASK_COMM_BUFFER_SIZE_MESSAGE);
	LibQueue_Initialize( &m_t_QueueMessage[MESSAGE_ADDRESS_SLAVE],
			    (uint8 *)&m_u8_BufferMessage[MESSAGE_ADDRESS_SLAVE],
			    TASK_COMM_BUFFER_SIZE_MESSAGE );
}

//Private function definition   私有函数定义
static uint TaskComm_InitializeBle(void)
{
	
	Ble_SetConfig(BLE_PARAM_CALLBACK_ON_WRITE,
		      (uint8 *)TaskComm_BleOnWrite,
		      sizeof(fp_on_write));
	Ble_SetConfig(BLE_PARAM_CALLBACK_ON_CONNECT,
		      (uint8 *)TaskComm_BleOnConnect,
		      sizeof(fp_on_connect));
	Ble_SetConfig(BLE_PARAM_CALLBACK_ON_DISCONNECT,
		      (uint8 *)TaskComm_BleDisOnConnect,
		      sizeof(fp_on_disconnect));
	Ble_SetConfig(BLE_PARAM_CALLBACK_ON_TIMRCHECK,
		      (uint8 *)TaskComm_BleTimerCheck,
		      sizeof(fp_on_timercheck));
	TaskComm_InitFrame(COMM_OPERATION_WRITE);
	TaskComm_InitFrame(COMM_OPERATION_READ);
	TaskComm_InitDeviceEvent();
	return FUNCTION_OK;
}

static uint TaskComm_InitializeComm(void)
{
	devcomm_profile t_Profile;
	devcomm_callback t_Callback;
	
	t_Profile.t_Address = MESSAGE_ADDRESS_MASTER;
	t_Profile.t_PacketLengthMax = TASK_COMM_PACKET_LENGTH_MAX;
	t_Profile.u16_Retry = TASK_COMM_SEND_RETRY;
	t_Profile.u16_Timeout = TASK_COMM_SEND_TIMEOUT;
	
	t_Callback.fp_HandleEvent = TaskComm_HandleEvent;
	t_Callback.fp_WriteDevice = TaskComm_WriteDevice;
	t_Callback.fp_ReadDevice = TaskComm_ReadDevice;
	t_Callback.fp_Memcpy = TaskComm_Memcpy;
	t_Callback.fp_GetCRC8 = TaskComm_GetCRC8;
	t_Callback.fp_GetCRC16 = TaskComm_GetCRC16;
	t_Callback.fp_EncryptionUpdate = TaskComm_EncryptionUpdate;
	t_Callback.fp_Encrypt = TaskComm_Encrypt;
	t_Callback.fp_Decrypt = TaskComm_Decrypt;
	t_Callback.fp_EnterCritical = (devcomm_callback_enter_critical)0;
	t_Callback.fp_ExitCritical = (devcomm_callback_exit_critical)0;
	if ( DevComm_Initialize(TASK_COMM_DEVICE_RF,
				&t_Profile,
				&t_Callback) != FUNCTION_OK )
		return FUNCTION_FAIL;
	
	if ( DevComm_Link( TASK_COMM_DEVICE_RF,
			  MESSAGE_ADDRESS_MASTER,
			  TASK_COMM_PACKET_LENGTH_MASTER ) != FUNCTION_OK )
		return FUNCTION_FAIL;
	
	// if ( DevComm_Link( TASK_COMM_DEVICE_RF,
	//                    MESSAGE_ADDRESS_SLAVE,
	//                    TASK_COMM_PACKET_LENGTH_SLAVE ) != FUNCTION_OK )
	// 	return FUNCTION_FAIL;
	// LOG_INFO("02");
	
	if ( DevComm_SwitchEncryption( TASK_COMM_DEVICE_RF,
				      MESSAGE_ADDRESS_MASTER,
				      DEVCOMM_ENCRYPTION_OFF ) != FUNCTION_OK )
		return FUNCTION_FAIL;
	
	// if ( DevComm_SwitchEncryption( TASK_COMM_DEVICE_RF,
	//                                MESSAGE_ADDRESS_SLAVE,
	//                                DEVCOMM_ENCRYPTION_OFF ) != FUNCTION_OK )
	//     return FUNCTION_FAIL;
	// REG_SET_BIT(m_ui_Flag[MESSAGE_ADDRESS_SLAVE], TASK_COMM_FLAG_SWITCH);
	REG_SET_BIT(m_ui_Flag[MESSAGE_ADDRESS_MASTER], TASK_COMM_FLAG_SWITCH);
	
	
	// LibQueue_Initialize( &m_t_QueueMessage[MESSAGE_ADDRESS_SLAVE],
	//                      (uint8 *)&m_u8_BufferMessage[MESSAGE_ADDRESS_SLAVE],
	//                      TASK_COMM_BUFFER_SIZE_MESSAGE );
	
	LibQueue_Initialize( &m_t_QueueMessage[MESSAGE_ADDRESS_MASTER],
			    (uint8 *)&m_u8_BufferMessage[MESSAGE_ADDRESS_MASTER],
			    TASK_COMM_BUFFER_SIZE_MESSAGE );
	return FUNCTION_OK;
}

static uint TaskComm_InitializeOS
( 
devos_task_handle t_TaskHandle
)
{
	if (Task_ObtainMessageID(&m_ui_MessageID) != FUNCTION_OK)
		return FUNCTION_FAIL;
	
	if ( DevOS_MessageInitialize( (devos_int)m_ui_MessageID,
				     (uint8 *)0,
				     0 ) != FUNCTION_OK )
		return FUNCTION_FAIL;
	
	if ( DevOS_MessageRegister( (devos_int)m_ui_MessageID,
				   t_TaskHandle ) != FUNCTION_OK)
	{
		return FUNCTION_FAIL;
	}
	
	
	
	return FUNCTION_OK;
	
}
static void TaskComm_InitDeviceEvent(void)
{
	LibQueue_Initialize( &m_t_QueueDeviceEvent,
			    m_u8_BufferDeviceEvent,
			    TASK_COMM_BUFFER_SIZE_DEVICE_EVENT) ;
}
void TaskComm_InitFrame
( 
uint ui_Operation
)
{
	comm_control * tp_Control;
	if(ui_Operation >= COMM_COUNT_OPERATION)
		return;
	tp_Control = &m_t_CommControl[ui_Operation]; 
	LibQueue_Initialize( &tp_Control->t_QueueData,
			    tp_Control->u8_BufferData,
			    m_u8_BufferSize[ui_Operation] );
	LibQueue_Initialize( &tp_Control->t_QueueLength,
			    tp_Control->u8_BufferLength,
			    sizeof(tp_Control->u8_BufferLength) );
}

static uint TaskComm_GetDevice
( 
devcomm_int t_Address,
devcomm_int *tp_Device 
)
{
	switch (t_Address){
	    case MESSAGE_ADDRESS_MASTER:
		*tp_Device = TASK_COMM_DEVICE_RF;
		break;
		
	    case MESSAGE_ADDRESS_SLAVE:
		*tp_Device = TASK_COMM_DEVICE_RF;
		break;
		
	    default:
		return FUNCTION_FAIL;
	}
	
	if (REG_GET_BIT(m_ui_Flag[t_Address], TASK_COMM_FLAG_SWITCH) == 0)
		return FUNCTION_FAIL;
	
	return FUNCTION_OK;
}

static uint TaskComm_CheckCommandPending
( 
devcomm_int t_Address 
)
{
	uint ui_Value;
	devcomm_int t_State;
	devcomm_int t_Device;
	devcomm_int t_CommandLength;
	task_comm_message t_Message;
	
	if ( TaskComm_GetDevice(t_Address, &t_Device) != FUNCTION_OK )
		return FUNCTION_FAIL;
	
	if ( DevComm_Query(t_Device, t_Address, DEVCOMM_INFO_STATE, &t_State) != FUNCTION_OK )
		return FUNCTION_FAIL;
	
	if ( t_State == DEVCOMM_STATE_BUSY )
		return FUNCTION_FAIL;
	
	ui_Value = sizeof(t_Message);
	if ( LibQueue_PopHead( &m_t_QueueMessage[t_Address],
			      (uint8 *)&t_Message,
			      &ui_Value ) != FUNCTION_OK )
		return FUNCTION_FAIL;
	if (ui_Value < sizeof(t_Message))
		return FUNCTION_FAIL;
	
	t_CommandLength = (devcomm_int)t_Message.u8_Length;
	ui_Value = (uint)t_CommandLength;
	if ( LibQueue_PopHead( &m_t_QueueMessage[t_Address],
			      m_u8_BufferCommand,
			      &ui_Value ) != FUNCTION_OK )
		return FUNCTION_FAIL;
	
	if ( REG_GET_BIT(m_ui_Flag[t_Address], TASK_COMM_FLAG_SWITCH) == 0 )
		return FUNCTION_FAIL;
	
	return DevComm_Send( t_Device,
			    t_Address,
			    (devcomm_int)t_Message.u8_SourcePort,
			    (devcomm_int)t_Message.u8_TargetPort,
			    m_u8_BufferCommand,
			    t_CommandLength,
			    (devcomm_int)t_Message.u8_Mode );
}

static void TaskComm_Tick
( 
uint16 u16_TickTime
)
{
	DevComm_Tick(TASK_COMM_DEVICE_RF, u16_TickTime);
}

static void TaskComm_HandleMessage(void)
{
	uint ui_Event;
	uint ui_Length;
	uint8 *u8p_MessageData;
	devos_int t_MessageLength;
	devcomm_int t_Address;
	devcomm_int t_Device;
	
	for(t_Address = MESSAGE_ADDRESS_MASTER; t_Address <= MESSAGE_ADDRESS_MASTER; t_Address++)
	{
		
		if (TaskComm_GetDevice(t_Address, &t_Device) != FUNCTION_OK)
			continue;
		
		u8p_MessageData = DevOS_MessageReceive( (devos_int)m_ui_MessageID,
						       &t_MessageLength );
		if (u8p_MessageData == (const uint8 *)0)
			continue;
		
		ui_Length = sizeof(ui_Event);
		
		Task_EnterCritical();
		
		while ( LibQueue_PopHead( &m_t_QueueDeviceEvent,
					 (uint8 *)&ui_Event,
					 &ui_Length ) == FUNCTION_OK )
		{
			Task_ExitCritical();
			
			if (REG_GET_BIT(m_ui_Flag[t_Address], TASK_COMM_FLAG_SWITCH) != 0)
			{
				if(ui_Event == TASK_COMM_EVENT_WRITE_DONE)
				{
					DevComm_WriteDeviceDone(t_Device);
				}
				else if (ui_Event == TASK_COMM_EVENT_READ_DONE)
				{
					DevComm_ReadDeviceDone( t_Device,
							       m_u8p_ReadData,
							       (devcomm_int)m_ui_ReadLength );
				}
			}
			
			Task_EnterCritical();
		}
		
		Task_ExitCritical();
		
		TaskComm_CheckCommandPending(t_Address);
	}
	u8p_MessageData = DevOS_MessageReceive(TASK_MESSAGE_ID_TICK, &t_MessageLength);
	
	if (u8p_MessageData != (const uint8 *)0)
		TaskComm_Tick(*((uint16 *)u8p_MessageData));
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static uint TaskComm_CheckState
(
uint8 *u8p_State
)
{
	uint ui_Event;
	uint ui_Length;
	devcomm_int t_Address;
	devcomm_int t_Device;
	devcomm_int t_State;
	
	
	*u8p_State = 0;
	
	t_Device = MESSAGE_ADDRESS_MASTER;
	
	if (TaskComm_GetDevice(t_Address, &t_Device) == FUNCTION_OK)
	{
		if (DevComm_Query(t_Device, t_Address, DEVCOMM_INFO_STATE, 
				  &t_State) != FUNCTION_OK)
		{
			return FUNCTION_FAIL;
		}
		
		if (t_State == DEVCOMM_STATE_BUSY) 
		{
			*u8p_State = 1;
		}
		
		ui_Length = sizeof(ui_Event);
		
		if (LibQueue_PeekHead(&m_t_QueueDeviceEvent, 
				      (uint8 *)&ui_Event, &ui_Length) == FUNCTION_OK)
		{
			*u8p_State = 1;
		}
	}
	
	return FUNCTION_OK;
}



static uint TaskComm_HandleEvent
( 
devcomm_int t_Device,
devcomm_int t_Address,
devcomm_int t_SourcePort,
devcomm_int t_TargetPort,
devcomm_int t_Event
)
{
	uint ui_Value;
	uint ui_Acknowledge;
	uint8 u8_Port;
	devcomm_int t_Length;
	devcomm_int t_Mode;
	message_command t_Command;
	LOG_INFO("TaskComm_HandleEvent");
	if (TaskComm_GetDevice(t_Address, &t_Device) != FUNCTION_OK)
		return FUNCTION_FAIL;
	
	if (REG_GET_BIT(m_ui_Flag[t_Address], TASK_COMM_FLAG_SWITCH) == 0)
		return FUNCTION_FAIL;
	
	switch (t_Event) {
	    case MESSAGE_EVENT_TIMEOUT:
		Task_SendMessage(m_ui_MessageID, (const uint8 *)0, 0);
		return FUNCTION_OK;
		
	    case MESSAGE_EVENT_RECEIVE_DONE:
		LOG_INFO("TaskComm_HandleEvent:MESSAGE_EVENT_RECEIVE_DONE");
		t_Length = sizeof(m_u8_BufferCommand);
		if ( DevComm_Receive( t_Device,
				     t_Address,
				     &t_SourcePort,
				     &t_TargetPort,
				     m_u8_BufferCommand,
				     &t_Length,
				     &t_Mode ) != FUNCTION_OK )
			return FUNCTION_FAIL;
		if (t_Length < MESSAGE_COUNT_COMMAND_OFFSET)
			return FUNCTION_FAIL;
		
		t_Command.u8_Operation = m_u8_BufferCommand[MESSAGE_COMMAND_OFFSET_OPERATION];
		t_Command.u8_Parameter = m_u8_BufferCommand[MESSAGE_COMMAND_OFFSET_PARAMETER];
		t_Command.u8_Length = (uint8)t_Length - MESSAGE_COUNT_COMMAND_OFFSET;
		t_Command.u8p_Data = m_u8_BufferCommand + MESSAGE_COUNT_COMMAND_OFFSET;
		LOG_INFO("cmd operation:0x%02x",t_Command.u8_Operation);
		LOG_INFO("cmd u8_Parameter:0x%02x",t_Command.u8_Parameter);
		LOG_INFO("cmd u8_Length:0x%02x",t_Command.u8_Length);
		for(uint8 i = 0; i < t_Command.u8_Length; i++)
		{
			LOG_INFO("Data[%d]:0x%02x",i,t_Command.u8p_Data[i]);
		}
		switch (t_Command.u8_Operation) {
		    case MESSAGE_OPERATION_SET:
#if TASK_COMM_SET_AUTHORITY
			if ( REG_GET_BIT(m_ui_Flag[t_Address], TASK_COMM_FLAG_PRIMARY) == 0 )
				return FUNCTION_FAIL;
#endif
		    case MESSAGE_OPERATION_GET:
			if ( REG_GET_BIT(m_ui_Flag[t_Address], TASK_COMM_FLAG_BONDED) == 0 )
				return FUNCTION_FAIL;
			break;
		    default:
			break;
		}
		
		u8_Port = MESSAGE_GET_MAJOR_PORT((uint8)t_TargetPort);
		switch (u8_Port) {
		    case MESSAGE_PORT_TASK:
			ui_Acknowledge = Task_HandleCommand( (uint8)t_SourcePort,
							    (uint8)t_TargetPort,
							    &t_Command );
			break;
			
		    default:
			ui_Acknowledge = FUNCTION_FAIL;
			break;
		}
		
		if (ui_Acknowledge == FUNCTION_OK)
		{
			switch (t_Command.u8_Operation){
			    case MESSAGE_OPERATION_NOTIFY:
			    case MESSAGE_OPERATION_ACKNOWLEDGE:
			    case MESSAGE_OPERATION_PAIR:
			    case MESSAGE_OPERATION_UNPAIR:
			    case MESSAGE_OPERATION_BOND:
	            return TaskComm_Send( (uint8)t_Address,
							       (uint8)t_TargetPort,
							       (uint8)t_SourcePort,
							       &t_Command,
							       MESSAGE_MODE_ACKNOWLEDGEMENT );

				
			    default:
				if ( LibQueue_GetConfig( &m_t_QueueMessage[t_Address],
							LIB_QUEUE_PARAM_BUFFER_SPACE,
							(void *)&ui_Value ) == FUNCTION_OK )
				{
					if ( ui_Value >= m_u8_BufferMessageLength[t_Address] &&
					    t_Command.u8_Operation == MESSAGE_OPERATION_EVENT &&
						    t_Mode == MESSAGE_MODE_ACKNOWLEDGEMENT              )
					{
						return TaskComm_Send( (uint8)t_Address,
								     (uint8)t_TargetPort,
								     (uint8)t_SourcePort,
								     &t_Command,
								     MESSAGE_MODE_NO_ACKNOWLEDGEMENT );
					}
				}
			}
		}
		
		return ui_Acknowledge;
		
	    default:
		return FUNCTION_FAIL;
	}
}


static uint TaskComm_WriteDevice
( 
devcomm_int t_Device,
const uint8 *u8p_Data,
devcomm_int t_Length 
)
{
	LOG_INFO("TaskComm_WriteDevice");
	switch (t_Device) 
	{
		
	    case TASK_COMM_DEVICE_RF:
		return TaskComm_Write(u8p_Data,
				      (uint)t_Length );
		
	    default:
		return FUNCTION_FAIL;
	}
	return FUNCTION_OK;
}


static uint TaskComm_Write
( 
const uint8 *u8p_Data,
uint ui_Length 
)
{
	LOG_INFO("TaskComm_Write");
	comm_control *tp_Control = &m_t_CommControl[COMM_OPERATION_WRITE]; 
	uint ui_Value;
	if (u8p_Data != (const uint8 *)0)
	{
		LibQueue_GetConfig( &tp_Control->t_QueueLength,
				   LIB_QUEUE_PARAM_BUFFER_SPACE,(void *)&ui_Value ) ;
		
		
		if ( TaskComm_AddFrame( COMM_OPERATION_WRITE,
				       u8p_Data,
				       ui_Length ) != FUNCTION_OK )
		{
			TaskComm_HandleDeviceRfEvent(TASK_COMM_EVENT_WRITE_DONE,(const uint8 *)0, 0 );
			return FUNCTION_FAIL;
		}
		
		
		if (ui_Value >= sizeof(tp_Control->u8_BufferLength))
		{
			return TaskComm_ProcessFrame(COMM_OPERATION_WRITE,
						     u8p_Data,
						     ui_Length );
		}
		
		return FUNCTION_OK;
	}
	else
	{
		ui_Length = sizeof(ui_Value);
		if ( LibQueue_PeekHead( &tp_Control->t_QueueLength,
				       (uint8 *)&ui_Value,
				       &ui_Length ) != FUNCTION_OK )
			return FUNCTION_FAIL;
		ui_Length = ui_Value;
		
		if ( LibQueue_GetConfig( &tp_Control->t_QueueData,
					LIB_QUEUE_PARAM_HEAD,
					(void *)&ui_Value ) != FUNCTION_OK )
			return FUNCTION_FAIL;
		
		return TaskComm_ProcessFrame( COMM_OPERATION_WRITE,
					     tp_Control->u8_BufferData + ui_Value,
					     ui_Length );
	}
}


static uint TaskComm_ReadDevice
( 
devcomm_int t_Device,
uint8 *u8p_Data,
devcomm_int *tp_Length 
)
{
	uint ui_Length = (uint)(*tp_Length);;
	uint ui_Return;
	
	switch (t_Device) 
	{
	    case TASK_COMM_DEVICE_RF:
		ui_Return = TaskComm_Read( u8p_Data,
					  &ui_Length );
		break;
		
	    default:
		ui_Return = FUNCTION_FAIL;
		break;
	}
	
	*tp_Length = (devcomm_int)ui_Length;
	
	return ui_Return;
}

static uint TaskComm_Read
(
uint8 *u8p_Data,
uint *uip_Length 
)
{
	uint ui_Value;
	uint ui_Length = sizeof(ui_Value);
	if ( TaskComm_PopFrame(COMM_OPERATION_READ,
			       u8p_Data,
			       uip_Length ) != FUNCTION_OK )
		return FUNCTION_FAIL;
	
	comm_control *tp_Control = &m_t_CommControl[COMM_OPERATION_READ]; 
	
	
	if ( LibQueue_PeekHead( &tp_Control->t_QueueLength,
			       (uint8 *)&ui_Value,
			       &ui_Length ) != FUNCTION_OK )
		return FUNCTION_OK;
	
	ui_Length = ui_Value;
	if ( LibQueue_GetConfig( &tp_Control->t_QueueData,
				LIB_QUEUE_PARAM_HEAD,
				(void *)&ui_Value ) != FUNCTION_OK )
		return FUNCTION_FAIL;
	
	return TaskComm_ProcessFrame(COMM_OPERATION_READ,
				     tp_Control->u8_BufferData + ui_Value,
				     ui_Length );
}
static void TaskComm_Memcpy
( 
uint8 *u8p_Target, 
const uint8 *u8p_Source, 
devcomm_int t_Length 
)
{
	Lib_Memcpy(u8p_Target, u8p_Source, (uint)t_Length);
}


static uint8 TaskComm_GetCRC8
( 
const uint8 *u8p_Data, 
devcomm_int t_Length, 
uint8 u8_Base 
)
{
	return LibChecksum_GetChecksumPartial8Bit(u8p_Data, (uint16)t_Length, u8_Base);
}


static uint16 TaskComm_GetCRC16
( 
const uint8 *u8p_Data, 
devcomm_int t_Length, 
uint16 u16_Base 
)
{
	return LibChecksum_GetChecksumPartial16Bit(u8p_Data, (uint16)t_Length, u16_Base);
}

static void TaskComm_EncryptionUpdate(void)
{
	AES_SetKey(0, m_u8_TempIv);
}

static void TaskComm_Encrypt
( 
uint8 *u8p_Data, 
devcomm_int t_Length 
)
{
	AES_CFB_encrypt((uint8_t *)u8p_Data, t_Length);
}

static void TaskComm_Decrypt
( 
uint8 *u8p_Data, 
devcomm_int t_Length 
)
{
	AES_CFB_decrypt((uint8_t *)u8p_Data, t_Length);
}


static uint TaskComm_SavePairingInfo(void)
{
	return Record_SavePairInfo(m_t_PairingInfo,TASK_COMM_COUNT_IDENTIFIER);
}
static uint TaskComm_LoadPairingInfo(void)
{
	return  Record_SavePairInfo(m_t_PairingInfo,TASK_COMM_COUNT_IDENTIFIER);
}
static uint TaskComm_SendCommand
( 
uint8 u8_Address,
uint8 u8_SourcePort,
uint8 u8_TargetPort,
const message_command *tp_Command,
uint8 u8_Mode 
)
{
	devcomm_int t_Device;
	devcomm_int t_CommandLength;
	LOG_INFO("TaskComm_SendCommand");
	if ( TaskComm_GetDevice((devcomm_int)u8_Address, &t_Device) != FUNCTION_OK )
		return FUNCTION_FAIL;
	
	if ( REG_GET_BIT(m_ui_Flag[u8_Address], TASK_COMM_FLAG_SWITCH) == 0 )
		return FUNCTION_FAIL;
	
	uint8 *u8p_Command;
	u8p_Command = (uint8 *)0;
	t_CommandLength = 0;
	
	if (tp_Command != (const message_command *)0)
	{
		t_CommandLength = tp_Command->u8_Length + MESSAGE_COUNT_COMMAND_OFFSET;
		m_u8_BufferCommand[MESSAGE_COMMAND_OFFSET_OPERATION] = tp_Command->u8_Operation;
		m_u8_BufferCommand[MESSAGE_COMMAND_OFFSET_PARAMETER] = tp_Command->u8_Parameter;
		Lib_Memcpy( m_u8_BufferCommand + MESSAGE_COUNT_COMMAND_OFFSET,
			   tp_Command->u8p_Data,
			   (uint)tp_Command->u8_Length );
		u8p_Command = m_u8_BufferCommand;
	}
	return DevComm_Send( t_Device,
			    (devcomm_int)u8_Address,
			    (devcomm_int)u8_SourcePort,
			    (devcomm_int)u8_TargetPort,
			    u8p_Command,
			    t_CommandLength,
			    (devcomm_int)u8_Mode );
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void TaskComm_BleOnConnect(void)
{

	m_u8_UpdateKeyFlag =1;
	REG_CLEAR_BIT(m_ui_Flag[MESSAGE_ADDRESS_MASTER], TASK_COMM_FLAG_BONDED);
	REG_CLEAR_BIT(m_ui_Flag[MESSAGE_ADDRESS_MASTER], TASK_COMM_FLAG_PRIMARY);
	DevComm_Unlink( TASK_COMM_DEVICE_RF,
		       MESSAGE_ADDRESS_MASTER );
	DevComm_Link( TASK_COMM_DEVICE_RF,
		     MESSAGE_ADDRESS_MASTER,
		     TASK_COMM_PACKET_LENGTH_MASTER );
	DevComm_SwitchEncryption( TASK_COMM_DEVICE_RF,
				 MESSAGE_ADDRESS_MASTER,
				 DEVCOMM_ENCRYPTION_OFF );
	TaskComm_ClearQueueEvent(); 
	TaskComm_ClearQueueMessage();
	for(uint i = 0; i < COMM_COUNT_OPERATION; i++)
	{
		TaskComm_ResetFrame(i);
	}
}
static void TaskComm_BleDisOnConnect(void)
{
//	TaskComm_ClearQueueMessage();
//for(uint i = 0; i < COMM_COUNT_OPERATION; i++)
//{
//TaskComm_ResetFrame(i);
//}
}

static void Task_TimerCheck(void *a)
{
	LOG_INFO("Ble_Proactively_disconnect\n");
	
	uint8 u8_Value = 1 ;
	DrvTimer_SetConfig(DRV_TIMER_ID3 ,DRV_TIMER_PARAM_TIMEOUTFLAG ,&u8_Value ,0) ;
	//断开连接
	Ble_Proactively_disconnect();
}
static void TaskComm_BleTimerCheck(void)
{
	DrvTimer_Finsh(DRV_TIMER_ID3);
	DrvTimer_Start(DRV_TIMER_ID3 ,PROCTIVELY_DISCONNECT ,0 ,Task_TimerCheck) ;
	
}

static void TaskComm_BleOnWrite
(
uint16 u16_ConnetHandle, 
uint16 u16_AttIndex, 
uint8 *u8p_Data, 
uint16 u16_Len
)
{
	(void)u16_ConnetHandle;
	LOG_INFO("TaskComm_BleOnWrite:%d",u16_AttIndex);
	switch (u16_AttIndex)
	{
	    case COMMUNICATION_INDEX:
		{
			TaskComm_CommunicationServicOnWrite(u8p_Data,u16_Len);
		}
		break;
	    case MANAGEMENT_INDEX:
		{
			TaskComm_ManagementServicOnWrite(u8p_Data,u16_Len);
			
		}
		break;
	    default:
		return;
	}
}
static void TaskComm_CommunicationServicOnWrite
(
uint8 * u8p_Data, 
uint16 u16_Length
)
{
	static uint8 u8_Count = 0;
	static uint16 u16_BufferPointer = 0;
	uint8 u8_Index;
	uint8 u8_Finish;
	
	u8_Index = (u8p_Data[u16_Length-1] & 0xF0) >> 4;
	u8_Finish = u8p_Data[u16_Length-1] & 0x0F;
	
	if (u8_Count != u8_Index || u16_BufferPointer + u16_Length-1 > RECEIVE_BUFFER_SIZE)
	{
		u16_BufferPointer = 0;
		u8_Count = u8_Index;
	}
		Lib_Memcpy(m_u8_ReceiveBuff+u16_BufferPointer, u8p_Data, u16_Length-1);
	u16_BufferPointer += u16_Length-1;
	if (u8_Finish != 0)
	{
		TaskComm_CommandReceived(m_u8_ReceiveBuff,u16_BufferPointer);
		//		for(uint i = 0 ; i<sizeof(m_u8_ReceiveBuff) ;i++)
		//		printf("m_u8_ReceiveBuff[%d]=%d\n",i,m_u8_ReceiveBuff[i]);
		u16_BufferPointer = 0;
	}
	
}

static void TaskComm_ManagementServicOnWrite
(
uint8 * u8p_Data, 
uint16 u16_Length
)
{
	uint8 u8_Result =1;
	if ( Lib_Memcmp(u8p_Data, m_u8_Reboot, sizeof(m_u8_Reboot)) == FUNCTION_OK )
	{
		LOG_INFO("soft Reset!!!");
		TaskRF_ManageMentNotify(MANAGEMENT_INDEX,&u8_Result,1);
		//		Drv_SoftRest(); 
	}
	if ( Lib_Memcmp(u8p_Data, m_u8_RebootAsc, sizeof(m_u8_RebootAsc)) == FUNCTION_OK )
	{
		LOG_INFO("Gc Reset!!!");
		TaskRF_ManageMentNotify(MANAGEMENT_INDEX,&u8_Result,1);
		//		 Gc_Reset();
	}
	if ( Lib_Memcmp(u8p_Data, m_u8_GetR, sizeof(m_u8_GetR)) == FUNCTION_OK )//cmd  Get R
	{ 
		LOG_INFO("Get R");
		TaskRF_ManageMentNotify(MANAGEMENT_INDEX,&u8_Result,1);
		//		 TaskClucose_GetRParam(u8p_Data, &u16_Length);
		//		 TaskRF_ManageMentNotify(BLE_SV_MANAGEMENT,u8p_Data,u16_Length);
	}
	if ( Lib_Memcmp(u8p_Data, m_u8_CalR, sizeof(m_u8_CalR)) == FUNCTION_OK )//cmd Cal R
	{
		LOG_INFO("Cal R");
		TaskRF_ManageMentNotify(MANAGEMENT_INDEX,&u8_Result,1);
		// TaskClucose_SetCalibrateRFlag();
	}
	if ( Lib_Memcmp(u8p_Data, m_u8_GetPairInfo1, sizeof(m_u8_GetPairInfo1)) == FUNCTION_OK )
	{
		LOG_INFO("Get Pair Info 0");
		TaskRF_ManageMentNotify(MANAGEMENT_INDEX,&u8_Result,1);
		// Lib_Memset(u8_Data,0,sizeof(u8_Data));
		// Lib_Memcpy(u8_Data,m_t_PairingInfo[0].u8_PairingID,14);
		// Lib_Memcpy(u8_Data+14,m_t_PairingInfo[0].u8_BondID,6);
		// TaskRF_ManageMentNotify(BLE_SV_MANAGEMENT,u8_Data,20);
	}
	if ( Lib_Memcmp(u8p_Data, m_u8_GetPairInfo2, sizeof(m_u8_GetPairInfo2)) == FUNCTION_OK )
	{
		LOG_INFO("Get Pair Info 1");
		TaskRF_ManageMentNotify(MANAGEMENT_INDEX,&u8_Result,1);
		// Lib_Memset(u8_Data,0,sizeof(u8_Data));
		// Lib_Memcpy(u8_Data,m_t_PairingInfo[1].u8_PairingID,14);
		// Lib_Memcpy(u8_Data+14,m_t_PairingInfo[1].u8_BondID,6);
		// TaskRF_ManageMentNotify(BLE_SV_MANAGEMENT,u8_Data,20);
	}
	
	if ( Lib_Memcmp(u8p_Data, m_u8_Log, sizeof(m_u8_Log)) == FUNCTION_OK )
	{
		LOG_INFO("Get Log");
		TaskRF_ManageMentNotify(MANAGEMENT_INDEX,&u8_Result,1);
		// uint16 * u16p_Index = (uint16 *)(&u8p_Data[3]);
		//     #if CGMS_LOG_SW
		// t_log t_Log;
		
		// if(TaskMonitor_LoadLog( *u16p_Index,&t_Log ))
		// {
		//         TaskRF_ManageMentNotify(BLE_SV_MANAGEMENT,(uint8 *)&t_Log,sizeof(t_Log));
		// }
		// else
		// {
		
		// }
		
		// #endif
	}
	if ( Lib_Memcmp(u8p_Data, m_u8_GetLogNum, sizeof(m_u8_GetLogNum)) == FUNCTION_OK )
	{
		LOG_INFO("Get Log Num");
		TaskRF_ManageMentNotify(MANAGEMENT_INDEX,&u8_Result,1);
		// #if CGMS_LOG_SW
		// uint16 u16_LogHeaderIndex = TaskMonitor_GetLogHeadIndex();
		// TaskRF_ManageMentNotify(BLE_SV_MANAGEMENT,(uint8 *)&u16_LogHeaderIndex,(uint8_t) sizeof(u16_LogHeaderIndex));
		// #endif
	}
	if ( Lib_Memcmp(u8p_Data, m_u8_ClearPairingInfo, sizeof(m_u8_ClearPairingInfo)) == FUNCTION_OK )
	{
		LOG_INFO("Clear pair info ");
		TaskRF_ManageMentNotify(MANAGEMENT_INDEX,&u8_Result,1);
		// app_sched_event_put(0,0, TaskComm_HandlerClearPairInfo);
		
	}
	
}

static void TaskComm_CommandReceived
(
uint8 * u8p_Data, 
uint16 u16_Length
)
{
	LOG_INFO("TaskComm_CommandReceived");
	comm_control * tp_Control = &m_t_CommControl[COMM_OPERATION_READ];
	uint ui_Value;
	LibQueue_GetConfig( &tp_Control->t_QueueLength,
			   LIB_QUEUE_PARAM_BUFFER_SPACE,
			   (void *)&ui_Value );
	
	if( TaskComm_AddFrame(COMM_OPERATION_READ,
			      u8p_Data,
			      u16_Length ) != FUNCTION_OK )
		return;
	
	if (ui_Value >= sizeof(tp_Control->u8_BufferLength))//if first frame ,start process Frame 
	{
		Lib_Memcpy( m_u8_ReceiveBuffBak,u8p_Data,u16_Length );
		
		TaskComm_ProcessFrame(COMM_OPERATION_READ,
				      m_u8_ReceiveBuffBak,
				      u16_Length );
	}
}


void TaskComm_ResetFrame
( 
uint ui_Operation
)
{
	comm_control * tp_Control;
	if(ui_Operation >= COMM_COUNT_OPERATION)
		return;
	uint ui_Value = 1;
	tp_Control = &m_t_CommControl[ui_Operation]; 
	LibQueue_SetConfig( &tp_Control->t_QueueLength,
			   LIB_QUEUE_PARAM_BUFFER_CLEAR,
			   (void *)&ui_Value );
	LibQueue_SetConfig( &tp_Control->t_QueueData,
			   LIB_QUEUE_PARAM_BUFFER_CLEAR,
			   (void *)&ui_Value );
}

static uint TaskComm_AddFrame
( 
uint ui_Operation,
const uint8 *u8p_Data,
uint ui_Length 
)
{
	comm_control * tp_Control;
	uint ui_Value;
	if (ui_Length == 0)
		return FUNCTION_FAIL;
	if(ui_Operation >= COMM_COUNT_OPERATION)
		return FUNCTION_FAIL;
	tp_Control = &m_t_CommControl[ui_Operation]; 
	
	if ( LibQueue_GetConfig( &tp_Control->t_QueueData,
				LIB_QUEUE_PARAM_BUFFER_SPACE,
				(void *)&ui_Value ) != FUNCTION_OK )
		return FUNCTION_FAIL;
	
	if ( ui_Length > ui_Value )
	{
		TaskComm_ResetFrame(ui_Operation);
		return FUNCTION_FAIL;
	}
	
	ui_Value = sizeof(ui_Length);
	if ( LibQueue_PushTail( &tp_Control->t_QueueLength,
			       (const uint8 *)&ui_Length,
			       &ui_Value ) != FUNCTION_OK )
		
	{
		TaskComm_ResetFrame(ui_Operation);
		return FUNCTION_FAIL;
	}
	
	if ( LibQueue_PushTail( &tp_Control->t_QueueData,
			       u8p_Data,
			       &ui_Length ) != FUNCTION_OK )
	{
		TaskComm_ResetFrame(ui_Operation);
		return FUNCTION_FAIL;
	}
	return FUNCTION_OK;
}


static uint TaskComm_PopFrame//TaskComm_RemoveFrame
( 
uint ui_Operation,
uint8 *u8p_Data,
uint *uip_Length
)
{
	comm_control * tp_Control;
	uint ui_Value;
	uint ui_Length = sizeof(ui_Value);
	
	if (uip_Length == (uint *)0)
		return FUNCTION_FAIL;
	tp_Control = &m_t_CommControl[ui_Operation]; 
	
	//Check if there is any frame can be read
	if ( LibQueue_PopHead( &tp_Control->t_QueueLength,
			      (uint8 *)&ui_Value,
			      &ui_Length ) != FUNCTION_OK )
	{
		TaskComm_ResetFrame(ui_Operation);
		return FUNCTION_FAIL;
	}
	
	if (*uip_Length > ui_Value)
		*uip_Length = ui_Value;
	if ( LibQueue_PopHead( &tp_Control->t_QueueData,
			      u8p_Data,
			      uip_Length ) != FUNCTION_OK )
	{
		TaskComm_ResetFrame(ui_Operation);
		return FUNCTION_FAIL;
	}
	
	if ( LibQueue_GetConfig( &tp_Control->t_QueueLength,
				LIB_QUEUE_PARAM_BUFFER_SPACE,
				(void *)&ui_Value ) != FUNCTION_OK )
		return FUNCTION_FAIL;
	
	if ( ui_Value >= sizeof(tp_Control->u8_BufferLength) )
		TaskComm_ResetFrame(ui_Operation);
	
	return FUNCTION_OK;
}


static uint TaskComm_ProcessFrame
( 
uint ui_Operation,
const uint8 *u8p_Data,
uint ui_Length 
)
{
	LOG_INFO("TaskComm_ProcessFrame");
	uint8 u8_Value = 0;
	uint16 u16_Interval;
	switch (ui_Operation)
	{
	    case COMM_OPERATION_WRITE:
		if(Ble_GetConfig(BLE_PARAM_CONNECT_STATE,&u8_Value,0) != FUNCTION_OK)
			return FUNCTION_FAIL;
		if(u8_Value == 0)
			return FUNCTION_FAIL;
		
		Ble_GetConfig(BLE_PARAM_CONNECT_INTERVAL,(uint8 *)&m_u16_ConnectInterval,0); 
		
		
		
		u16_Interval = m_u16_ConnectInterval * m_u16_ConnectWriteDelayRatio;
		// u16_Interval = u16_Interval * 1250 /1000;
		
		TaskComm_StartWriteTimer(u16_Interval);
		
		// TaskRF_StartTimerWrite(APP_TIMER_TICKS(u16_Interval));
		
		TaskComm_Notify(COMMUNICATION_INDEX,(uint8 *)u8p_Data,ui_Length);
		
		break;
	    case COMM_OPERATION_READ:
		LOG_INFO("TaskComm_ProcessFrame:COMM_OPERATION_READ");
		TaskComm_HandleDeviceRfEvent( TASK_COMM_EVENT_READ_DONE,
					     u8p_Data,
					     ui_Length);
		break;    
	    default:
		return FUNCTION_FAIL;
		break;
	}
	
	
	return FUNCTION_OK;
}

static uint TaskComm_Notify
(    
uint16 u16_AttHandle,  
uint8 *u8p_Data, 
uint ui_Len
)
{
	static uint8 u8_count = 0;
	static uint16 u16_length = 0;
	static uint8 u8_Finished = 0;
	static uint8 u8_SendBuff[BLE_MTU -3];
	// static uint  temp_code =0;
	if(u16_AttHandle != COMMUNICATION_INDEX)
		return FUNCTION_FAIL;
	
	u8_count++;
	u16_length = 0;
	u8_Finished = 0;
	while(ui_Len > 0)
	{
		if(ui_Len > BLE_MTU -4)
		{
			u16_length = BLE_MTU -4;
			ui_Len -= BLE_MTU -4;
			u8_Finished = 0;
		}
		else
		{
			u16_length = ui_Len;
			ui_Len = 0;
			u8_Finished = 1;
		}
		Lib_Memset(u8_SendBuff,0,sizeof(u8_SendBuff));
		Lib_Memcpy( u8_SendBuff,u8p_Data,(uint) u16_length );
		u8p_Data += u16_length;
		u8_SendBuff[u16_length] =((u8_count<<4)& 0xF0) |(u8_Finished & 0x0F);
		u16_length++;
		
		Ble_AttributeNotify(COMMUNICATION_INDEX,u8_SendBuff,u16_length);
		
	}
	
	return FUNCTION_OK;
}





static void TaskComm_StartWriteTimer
(
uint16 u16_Interval
)
{
	LOG_INFO("TaskComm_StartWriteTimer");
	uint32 u32_Period = u16_Interval;
	bool b_Repeat = false;
	
	DrvTimer_Start(DRV_TIMER_ID2 ,u32_Period ,b_Repeat ,TaskComm_WrtieTimerCallback) ;
}


static void TaskComm_WrtieTimerCallback(void *a)
{
	uint8 u8_Value = 1 ;
	DrvTimer_SetConfig(DRV_TIMER_ID2 ,DRV_TIMER_PARAM_TIMEOUTFLAG ,&u8_Value ,0) ;
	TaskComm_WriteDone( );
}

static void TaskComm_WriteDone( void )
{
	comm_control *tp_Control = &m_t_CommControl[COMM_OPERATION_WRITE]; 
	uint ui_Value;
	uint ui_Length = m_u8_BufferSize[COMM_OPERATION_WRITE];
	
	TaskComm_PopFrame(COMM_OPERATION_WRITE,
			  (uint8 *)0,&ui_Length );
	
	LibQueue_GetConfig( &tp_Control->t_QueueLength,
			   LIB_QUEUE_PARAM_BUFFER_SPACE,(void *)&ui_Value ) ;
	
	if (ui_Value >= sizeof(tp_Control->u8_BufferLength))
	{
		
		TaskComm_HandleDeviceRfEvent(TASK_COMM_EVENT_WRITE_DONE,
					     (const uint8 *)0, 0 );
	}
	else
	{
		TaskComm_Write((const uint8 *)0, 0 );
	}
	
	
}


static uint TaskComm_HandleDeviceRfEvent
( 
uint ui_Event,
const uint8 *u8p_Data,
uint ui_Length 
)
{
	uint ui_Value;
	ui_Value = sizeof(ui_Event);
	if ( LibQueue_PushTail( &m_t_QueueDeviceEvent,
			       (const uint8 *)&ui_Event,
			       &ui_Value ) == FUNCTION_OK )
	{
		if (ui_Event == TASK_COMM_EVENT_READ_DONE)
		{
			m_u8p_ReadData = u8p_Data;
			m_ui_ReadLength = ui_Length;
		}
	}
	Task_SendMessage(m_ui_MessageID, (const uint8 *)0, 0);
	return FUNCTION_OK;
}
static void TaskComm_UpdateBroadcast(void)
{
	uint8 i;
	m_t_Broadcast.u8_RFSignal = 0;
	for (uint8 i=0; i<TASK_COMM_COUNT_IDENTIFIER; i++)
	{
		if (m_t_PairingInfo[i].u8_Role == ROLE_PRIMARY)
			REG_SET_BIT(m_t_Broadcast.u8_RFSignal, i);
	}
	for(i=TASK_COMM_BROADCAST_DATA_SIZE-6;i<TASK_COMM_BROADCAST_DATA_SIZE;i++)//Reserved broadcast packet last 6 byte
	{
		m_t_Broadcast.u8_Data[i] = 0xFF;
	}
	
	m_t_Broadcast.u8_Checksum = 
		LibChecksum_GetChecksum8Bit( (const uint8 *)&m_t_Broadcast,
					    sizeof(m_t_Broadcast) - sizeof(m_t_Broadcast.u8_Checksum) );
	Ble_UpdateAdvData((uint8 *)&m_t_Broadcast,sizeof(m_t_Broadcast));
	// LOG_INFO("TaskComm_UpdateBroadcast");
	
}

static void TaskComm_ClearQueueEvent(void)
{
	
	Lib_Memset(m_u8_BufferDeviceEvent,
		   0,sizeof(m_u8_BufferDeviceEvent));
	LibQueue_Initialize( &m_t_QueueDeviceEvent,
			    m_u8_BufferDeviceEvent,
			    TASK_COMM_BUFFER_SIZE_DEVICE_EVENT) ;
	
}
